home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d26
/
corwp30.arc
/
COREMAN.DOC
< prev
next >
Wrap
Text File
|
1991-11-19
|
67KB
|
1,251 lines
┌────────────────────────────────────────────────────────╖
│ ┌──╖┌──╖┌─╖ ┌──╖┌┬┬╖┌──╖┌─╖ ┌──╖┌─╖ ┌──╖ ┌──╖ ┌──╖ ║██
│ │╔═╝│╔╕║│║╙╖│ ═╣│││║│══║│║╙╖ │══║│║╙╖│╔╕║ ├─ ║ │╔╕║ ║██
│ │╙─╖│╙┘║│╔╕║│ ═╣│ ║│╔╕║│╔╕║ │╔═╝│╔╕║│╙┘║ ├─ ║┌╖│╙┘║ ║██
│ ╘══╝╘══╝╘╝╘╝╘══╝╘══╝╘╝╘╝╘╝╘╝ ╘╝ ╘╝╘╝╘══╝ ╘══╝╘╝╘══╝ ║██
│ ┌╖┌╖┌──╖┌──╖┌─╖ ┌──╖┌──╖┌─┬╖┌╖┌╖┌──╖┌╖ ║██
│ │║│║│ ═╣│ ═╣│║╙╖ │ ║│══║│ │║│║│║│══║│║ ║██
│ │╙┘║├─ ║│ ═╣│╔╕║ │║║║│╔╕║│║ ║│╙┘║│╔╕║│╙─╖ ║██
│ ╘══╝╘══╝╘══╝╘╝╘╝ ╘╩╩╝╘╝╘╝╘╩═╝╘══╝╘╝╘╝╘══╝ ║██
╘════════════════════════════════════════════════════════╝██
██████████████████████████████████████████████████████████
Copyright (c) 1991 Stefan Strack
All rights reserved
Email: stracks@vuctrvax (Bitnet)
stracks@ctrvax.vanderbilt.edu (Internet)
Mail: Dept. Pharmacology, 406 MRB
Vanderbilt Univ. Medical School
Nashville, TN 37232-6600
Phone: +615-322-4890, Fax: +615-343-6532
┌────────────────────╖
│ Table of Contents ║
╘════════════════════╝
Line
1. Files .............................................. 59
2. Introduction ....................................... 72
3. Hardware requirements .............................. 93
4. Configuration ...................................... 105
5. Menu options........................................ 294
5.1. Function keys ............................ 311
5.2. Top level menu ........................... 344
5.3. The Loader menu .......................... 365
5.4. The Monitor menu ......................... 424
6. Redcode ............................................ 457
6.1. Instruction set .......................... 496
6.2. Addressing modes ......................... 716
6.3. Preprocessor syntax ...................... 760
7. ICWS'88 extensions ................................. 931
7.1. Process limit ............................ 953
7.2. Address space ............................ 969
7.3. Descendant count ......................... 983
8. The Core Editor .................................... 1013
9. Run control switches ............................... 1099
10. Bugs ............................................... 1199
11. Version history .................................... 1218
This document contains graphics characters; make sure your printer
is set up properly before printing.
V3.0=> New features or changes in Version 3.0 are marked at the left margin.
┌────────────╖
│ 1. Files ║
╘════════════╝
CORE.DOC - Quick intro, what's new
COREMAN.DOC - Manual for CoreWar Pro
CORE.EXE - CoreWar Pro executable
CORE.SYS - Configuration file for CORE.EXE
CORESTD.SYS - Configuration file for ICWS'88 compatible battles
COREMUS.DEF - optional mouse driver
*.RED - sample Redcode programs
┌───────────────────╖
│ 2. Introduction ║
╘═══════════════════╝
Core War is a simulation game for program battles in a small virtual
memory space. The rules are detailed in the original articles by the
creator of Core War, A.K.Dewdney (Computer recreations column,
Scientific American, May 84, March 85, December(?) 86; compiled in
his book "The Armchair Universe"). CoreWar Pro is a MARS (Memory
Array Redcode Simulator), a Core War supervisory program that
schedules the execution of battle programs written in the
assembly-style language Redcode. CoreWar Pro is an integrated
environment for writing and debugging Redcode programs and for
running battles between two or more programs. The Redcode interpreter
supports a superset of the ICWS'88 (International Core War Standard
of 1988) instruction set (see 6.) and implements Jon Newman's
Three Proposals for Future Redcode Standards (see 7.).
V3.0=> The program is written in PDC Prolog 3.21.
┌────────────────────────────╖
│ 3. Hardware Requirements ║
╘════════════════════════════╝
CoreWar Pro runs under DOS on IBM compatible computers with floppy or
hard drive and DOS. A graphics card is not required, since the
program operates fully in text mode. Memory requirement depends on
the size of the Core (specified in CORE.SYS, default 8000) and on the
number of Redcode programs loaded. With a Core size of 8000 the
program will need less than 300K. The maximum Core size is 32757.
┌────────────────────╖
│ 4. Configuration ║
╘════════════════════╝
The program is started with
CORE [filename]
where the optional parameter "filename" specifies a configuration
file. If omitted, the file defaults to CORE.SYS.
The configuration file controls appearance and behavior of CoreWar
Pro. It consists of Prolog predicates that are consulted upon program
start. You can change the setup by modifying the file with a text
editor. All predicates are on a separate line, no blank lines are
permitted. Commenting text following the closing parenthesis of a
predicate is ignored. The CORE.SYS supplied with this release is a
sample configuration for a color display; there you can find examples
for most predicates described in the following.
If CoreWar Pro cannot find the configuration file, or predicates are
omitted from the file, the program will initialize from defaults.
predicate: coresize(CS)
occurs: 0..1
argument: CS = 0..32757, default = 8000
example: coresize(32000)
Coresize/1 determines the size of the virtual memory array (Core) in
number of addresses; the original rules refer to CS=8000, but for
Redcode debugging and test runs the Core can be much smaller. The
Core may contain up to 32757 addresses. The larger the Core array,
the longer before a battle concludes by extinction of a contestant.
V3.0=> address_space(AS)
occurs: 0..1
argument: AS = 0..CoreSize, default = CoreSize
example: address_space(2000)
Address_space/1 specifies the range of Core that is addressable from
a given instruction (see 7.2.). Numeric fields of instructions
are normalized to a range of -(AS/2) .. (AS/2)-1 (-1000 .. 999 in the
example). The entire Core is addressable by default (AS=CoreSize).
V3.0=> process_limit(PL)
occurs: 0..1
argument: PL = 1..32767, default = 1000
example: process_limit(64)
Process_limit/1 restricts the maximum number of processes allocated
to each program (see 7.1.). When the process number reaches
this limit, SPL will have the effect of a "JMP 1" instruction.
V3.0=> descendant_count(Switch)
occurs: 0..1
argument: Switch = on ; off, default = on
example: descendant_count(off)
Descendant_count/1 specifies how the B-field of the SPL (Split)
instruction is interpreted. If Switch=on, the B-field is taken to be
the "descendant count", i.e. the maximum number of children,
children's children etc. of the currently executing process (see
7.3.). An empty B-field is translated to "#32767" which amounts
to quasi-unbounded process spawning. If Switch=off, the B-field is
ignored in compliance with ICWS'88.
The value of this predicate has side-effects on behavior of the
non-standard stack- (PSH, POP, GSB, RET, SSZ) and process-control
instructions (SSP, RLS): If Switch=on, each SPL execution will create
a process-node with a unique process ID-number. Since the interpreter
assigns a private stack and a "suspended-process buffer" to each
process ID-number, these instruction will have effects local to the
executing process. With descendant_count disabled, no descendant tree
is built, and each process has an ID-number equal to the program-ID.
Consequently, one stack and one suspended-process buffer is shared
among all processes of a given program (see 6.1., 7.3.).
V3.0=> predicate: screensize(Rows,Columns)
occurs: 0..1
arguments: Rows: 25, 43, 50, 60 ..
Columns: 80, 132, ..
example: screensize(50,80)
By default, CoreWar Pro starts up using the current text mode for
displaying the Core arena (most commonly 25 rows by 80 columns). The
screensize/2 predicate is used to set the screen size to the
specified values. You need to have the appropriate graphics card to
use extended text modes (EGA for 43x80, VGA for 50x80, etc.).
predicate: windowcolors(WindowName,InsideColor,FrameColor)
occurs: 0..7
arguments: WindowName = main ; menu ; statusline ; dialog ;
message ; editor ; error
InsideColor = 0..255, default = 7 (statusline 122)
FrameColor = 0..255, default = 15
example: windowcolors(message,36,47)
This predicate specifies the appearance of several windows (main,
menu, ..) in the game environment. InsideColor and FrameColor are
integers in the range from 0 to 255 specifying the color of the
window inside and its frame respectively. If you have a monochrome
monitor and the Core War display is illegible using the provided
CORE.SYS, try color values 7 or 15. You can also delete all
windowcolors/3 predicates, since colors default to black and white.
V3.0=> predicate: controlmode(M1,M2,M3,M4,M5,M6,M7,M8,M9)
occurs: 0..1
arguments: M1,M2,..M8 = on ; off
defaults: (on,off,on,off,on,on,on,off,off)
example: controlmode(off,on,off,off,off,off,off,off,off)
Controlmode/9 describes the initial setting of run control and run
display parameters (see 9.). The order of arguments is the
same as in the "Run control" window.
predicate: prodisplay(ProcessNo,ExeColor,ExeChar,
WriteColor,WriteChar,
BreakColor,BreakChar)
occurs: 0..?
arguments: ProgramNo = 1..?
ExeColor = 0..255, default = MainWindowForeground
ExeChar = ASCII(32)..ASCII(255),
default = ASCII(48 + ProgramNo)
WriteColor = 0..255,
default = MainWindowForeground
WriteChar = ASCII(32)..ASCII(255),
default = ASCII(249) ('∙')
BreakColor = 0..255,
default = MainWindowForeground + 128,
BreakChar = ASCII(32)..ASCII(255),
default = ASCII(48 + ProgramNo)
example: prodisplay(1,32,'1',2,'█',175,'1')
Prodisplay/7 controls the appearance of processes when run in "visual
mode" (see 9.). Argument ExeColor is the color attribute for
the display of ExeChar, the character indicating the execution of
program ProgramNo. When ProgramNo writes to Core, it is shown by
displaying WriteChar with color WriteColor. When visual mode is
interrupted because a program faulted, a key was pressed, etc., the
address last executed is highlighted by BreakChar displayed with
color BreakColor.
predicate: exclude(ExStr)
occurs: 0..?
argument: ExStr = "DAT" ; "MOV" ; "ADD" ; "SUB" ; "JMP" ;
"JMZ" ; "JMN" ; "JMG" ; "DJZ" ; "DJN" ;
"CMP" ; "SPL" ; "PCT" ; "HLT" ; "GSB" ;
"RET" ; "PSH" ; "POP" ; "RND" ; "SSP" ;
"RLS" ; "EXC" ; "SSZ" ; "SLT" ;
"$" ; "@" ; "<" ; ">" ; "^" ; "/" ; "\"
example: exclude("EXC")
The exclude/1 predicate forces programs to use a subset of the
Redcode language - e.g. to enforce the ICWS'88 instruction set. ExStr
is a quoted opcode in all capitals or an addressing mode symbol.
predicate: editor(CommandString)
occurs: 0..1
argument: CommandString = DOS command string
example: editor("qed")
Use the editor/1 predicate to specify the file editor invoked by the
"Editor" selection from the main menu.
predicate: path(DosPathName)
occurs: 0..1
argument: DosPathName = valid drive:\pathname,
default = ""
example: path("D:\GAMES\COREWAR")
Path/1 specifies where CoreWar Pro looks for files when displaying a
directory listing. Files that the program expects in DosPathName are
programs (*.RED), and saved game states (*.DMP). If the path/1
predicate is omitted, CoreWar Pro will look for all files in the
current directory. E.g. path("b:") sets the directory path to drive
B:. Note: you must omit the trailing back-slash in the directory
name.
predicate: cycles(N)
occurs: 0..1
argument: N = Real
default: 100000
example: cycles(2500)
Cycles/1 sets the starting value for the count-down execution timer
(see also 9.).
┌───────────────────╖
│ 5. Menu options ║
╘═══════════════════╝
CoreWar Pro is a windowing environment driven by menus and dialog
windows. Menu items are selected with arrow keys and the <Return> key
or highlighted hot-keys; the escape key returns to the previous menu
on top and also cancels input in dialog windows. The main window
displays the progress of the Core battle and the message window
receives most text output (run information, status reports etc.). The
status line on the bottom of the screen informs if and what kind of
input the program will accept. From the top level menu the two
central modules Loader and Monitor can be selected, each represented
with its own submenu. Briefly, the Loader loads and installs Redcode
programs and the Monitor executes them.
┌──────────────────────╖
│ 5.1. Function keys ║
╘══════════════════════╝
You can use the function keys F1 to F6 to execute frequently used
commands. F2, F3 and F4 (RunV, Step, Watch) first set the appropriate
interrupt/view modes of the control panel, then start the interpreter
and finally reset the control panel to its previous state.
F1 (Load) Lets you select Redcode programs from a directory
listing until you press <Escape>. You are then prompted for one of
three ways to install the selected programs in Core (see 5.3.,
Install programs). This is equivalent to repeatedly selecting "Load
program" and then "Install programs" from the Loader submenu.
F2 (RunV) Starts the interpreter in visual mode using the
default settings for controlmode/9.
F3 (Step) Starts the interpreter in single-step (debugging)
mode.
F4 (Watch) Starts the interpreter in watch/single-step mode.
Watchpoints are set from within the Core Editor.
F5 (New) Clears the Core and unloads programs (= "Reset"/"Unload
programs" from the Loader submenu).
F6 (Cls) Clears the main window.
┌─────────┐
│Loader▒▒>│
│Monitor >│
│DOS │
┌───────────────────────╖ │Editor │
│ 5.2. Top level menu ║ │Quit │
╘═══════════════════════╝ └─────────┘
The top level menu provides access to the Loader and Monitor submenus
and exits the environment (Quit). In addition the following commands
are available from the main menu:
5.2.1 DOS. This selection starts up a DOS shell. "EXIT" returns
to the top level.
5.2.2 Editor. Invokes the editor specified in the editor/1 setup
predicate (see 4.) for editing Redcode programs etc..
┌─────────┐
│Loader▒▒>│
┌──────────────────────┐
│Load▒Redcode▒program▒▒│
│Install programs >│
│Load Core │
┌────────────────────────╖ │Dump Core │
│ 5.3. The Loader menu ║ │Reset >│
╘════════════════════════╝ └──────────────────────┘
The Loader submenu is used to make the preparations for a Core battle
such as loading programs from disk, installing them in Core, etc..
These are the items on the menu:
5.3.1 Load Redcode program. Reads a Recode source file from
disk, selected from a directory listing of files matching *.RED and
assembles the program into an internal representation of Redcode. You
V3.0=> can change the default file path or extension by pressing F4 (Mask)
in the directory window. A program is selected using cursor-control
keys or the first letter of the file name. Syntax errors are reported
in an error window, and the assembly status is reported after
completion. "Load Redcode program" can be repeated ad lib.; for each
successful assembly a new program image is stored in memory. A
description of Redcode syntax can be found in section 6.
5.3.2 Install programs. After all Redcode battle contestants
have been loaded from disk and successfully assembled, they need to
be installed in the circular memory array (Core). "Install programs"
offers three installation modes in a submenu:
(1) At random. Programs are installed with randomly scattered start
addresses while maintaining a minimum distance that can be specified.
(2) Maximum distance. Programs are installed into Core such that they
keep a maximum distance from one another. (3) Manually. The user is
prompted for the start address of each program.
5.3.3 Load Core. The Core War simulator allows to dump the
current state of execution (Core contents, programs, process control
blocks, process queue, stacks) to disk in order to resume with a
battle in progress at a later time. "Load Core" lets the user select
a core file (*.DMP) from a current directory listing and consults
(=reads) it. Load/Install programs and Load Core are mutually
exclusive options for preparing for execution.
5.3.4 Dump Core. See above item; dumps the current state of
execution to disk (default extension .DMP). This option is also
useful for making "back-ups" during a long-running battle. A .DMP
file is a plain ASCII-file that you can look at or modify with an
editor.
5.3.5 Reset. Allows to reset (clear) Core and/or program images
in order to start fresh. (a) "Uninstall programs" clears all Core
addresses and resets process control blocks, stacks, and the process
queue, (b) "Unload programs" does the same as (a) and also clears all
programs from memory (this corresponds to pressing F5). (c) "Reset
counter" resets the count-down execution timer to its start value
(specified in the configuration file, see 4). "Install
programs" will not work unless the Core is clear.
┌─────────┐
│Loader >│
│Monitor▒>│
┌───────────┐
│Run▒▒▒▒▒▒▒▒│
┌─────────────────────────╖ │Control >│
│ 5.4. The Monitor menu ║ │Edit Core │
╘═════════════════════════╝ └───────────┘
The Monitor is the program scheduler and Redcode interpreter; from
the Monitor menu you can start execution, control execution, inspect
or edit the Core contents. The menu entries are:
5.4.1 Run. This starts the round-robin scheduler executing
instructions of Redcode programs installed in Core. Execution is
interrupted when one of the interrupt conditions enabled on the
control panel (see 9.) applies. An interrupt window displays
the source of interrupt, the current process' program counter and the
instruction interrupted. You are then returned to the Monitor menu
from which execution can be restarted after the point of interrupt.
The "Run" command uses the current settings on the control panel (see
below and 9.). The F2-4 keys start execution with predefined
control settings (see 5.1.).
5.4.2 Control. Opens the "control panel" of the scheduler.
Several controls pertaining to execution interrupts (single step,
break on error etc.) and representation of the running processes
(visual, watch, etc.) can be enabled or disabled by toggling on or
off. The initial setting of the control parameters are defined by the
setup predicate controlmode/9 (see 4.). The effect of each
control parameter on execution is described in section 9.
5.4.3 Edit Core. This option starts the full-screen memory
editor in its own window. The Core Editor allows you to scroll
through the memory array and to modify the contents of addresses.
Core Editor commands are described in section 8.
┌──────────────╖
│ 6. Redcode ║
╘══════════════╝
CoreWar Pro deals with three forms of Redcode as shown in this
schema:
"Full Redcode" (program on disk)
│
│ Preprocessor
v
"Plain Redcode"
^
│ Assembler/Disassembler
v
"Machine code"
The Redcode programmer writes programs in "Full Redcode" using a text
editor. Full Redcode is Redcode with "syntactic sugar" (see
6.3.). In pre-3.0 versions of CoreWar Pro, the preprocessor was
a separate program (RPP.EXE) that converted Full Redcode files to
"Plain Redcode" files, ie Redcode with all labels, EQUates and
expressions resolved to numbers. Starting with version 3.0, the
preprocessor is integrated into the program loader and feeds Plain
Redcode directly into the assembler. The assembler in turn produces a
space-efficient internal representation of the code ("machine code").
Machine code is not visible to the user; in fact, the Core Editor
(see 8.) includes a disassembler that translates machine code
back into human-readable Plain Redcode for display.
Each Redcode instruction occupies one line. Plain Redcode
instructions consist of a three-letter opcode followed by zero, one
or two operands. Each operand is made up of an optional addressing
mode character (see 6.2.) followed by an integer. Each file
V3.0=> contains exactly one program. Execution starts at the first
executable (ie non-DAT) instruction unless a specific start
instruction is defined by an "END <Start>" statement.
┌────────────────────────╖
│ 6.1. Instruction set ║
╘════════════════════════╝
CoreWar Pro supports a superset of the International Core War
Standard of 1988 (ICWS'88) Redcode instruction set. Twelve of the 25
opcodes supported belong to the ICWS'88 (this includes DAT and the
END pseudo-opcode). The 13 non-standard opcodes fall into six
classes: (1) Opcodes listed by A.K.Dewdney that were never
incorporated into the standard (JMG, DJZ); (2) the proposed opcode
PCT; (3) the widely implemented, but non-standard RND; (4) additional
process-control opcodes (SSP, RLS, HLT), including the two-operand
version of SPL; (5) stack opcodes (GSB, RET, PSH, POP, SSZ); and (6)
the meta-interpreter opcode EXC. The SLT opcode was introduced in the
ICWS'88. Redcode warriors written for official tournaments must
obviously restrict themselves to the ICWS'88 instruction set and
addressing modes (see 6.2.). The alternate configuration file
CORESTD.SYS contains the appropriate exclude/1 statements to enforce
ICWS'88 compatibility (see 4.). In the listing below,
non-standard opcodes are indicated by a ⁿ.
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Data statement │ DAT │ B │ Non-executable; B is data value ║
║ │ │ │ ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
Store-Instructions
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Move │ MOV │ A B │ Move contents of A to B ║
║ │ │ │ ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Add │ ADD │ A B │ Add the A- and B-fields of A to ║
║ │ │ │ the A- and B-fields of B ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Sub │ SUB │ A B │ Subtract the A- and B-fields of A ║
║ │ │ │ from the A- and B-fields of B ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Randomⁿ │ RND │ A B │ Generate random number (range 0 .. ║
║ │ │ │ A-1) and store it in B ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
ADD and SUB will add and subtract integers in the range from -32768
to 32767. The result is normalized to the current address space.
Branch-Instructions
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Jump │ JMP │ A │ Transfer control to A ║
║ │ │ │ (unconditional) ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Jump if zero │ JMZ │ A B │ Transfer control to A if contents ║
║ │ │ │ of B is zero ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Jump if not zero │ JMN │ A B │ Transfer control to A if contents ║
║ │ │ │ of B is not zero ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Jump if greater │ JMG │ A B │ Transfer control to A if contents ║
║ than zeroⁿ │ │ │ of B is greater than zero ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Compare │ CMP │ A B │ If contents of A is equal to B ║
║ │ │ │ then skip one instruction ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Skip if less │ SLT │ A B │ If contents of A is less than B ║
║ than │ │ │ then skip one instruction ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
Counter-Instructions
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Decrement, jump │ DJZ │ A B │ Subtract 1 from B and jump to A ║
║ if zeroⁿ │ │ │ if contents of B is 0 ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Decrement, jump │ DJN │ A B │ Subtract 1 from B and jump to A ║
║ if not zero │ │ │ if contents of B is not 0 ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
Process-Instructions
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Split │ SPL │ A │ Split execution into next ║
║ │ │ │ instruction and A ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Split boundedⁿ │ SPL │ A B │ Split, B is descendant count ║
║ │ │ │ ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Haltⁿ │ HLT │ - │ Terminate execution of ║
║ │ │ │ (sub)process ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Suspendⁿ │ SSP │ - │ Suspend execution of all other ║
║ │ │ │ subprocesses ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Releaseⁿ │ RLS │ - │ Release suspended subprocesses ║
║ │ │ │ ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
Remarks: The two-operand version of SPL (Split bounded) implements
the descendant count modification introduced by Jon Newman (see
7.3.). The descendant_count/1 configuration predicate can be
used to enable/disable interpretation of SPLit's B-field (see
4.).
SSP temporarily suspends executions of all threads except the one
executing SSP. Processes remain suspended until either a RLS
instruction is executed or the unsuspended thread(s) terminate (i.e.
SSP, .., RLS, HLT is equivalent to SSP, .., HLT). SSP/RLS can be
used to bracket a "critical segment" or to preempt low-priority
V3.0=> subprocesses. If descendant_count is enabled (see 4.), RLS
will only release those processes that were suspended by the
currently executing process. With descendant_count off, RLS releases
all currently suspended processes. If processes are already suspended
when a SSP is executed, the currently active processes will be
appended to the list of suspended processes. RLS has no effect if no
processes are suspended.
Execution of the HLT (Halt) instruction has the same effect as
attempted execution of a data statement, except that HLT will not
trigger an error message.
Stack-Instructions
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Gosubⁿ │ GSB │ A │ Transfer control to A; push ║
║ │ │ │ current address onto stack ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Returnⁿ │ RET │ A │ Pop return address from stack, add ║
║ │ │ │ A, and transfer control to it ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Pushⁿ │ PSH │ A │ Push contents of A onto stack ║
║ │ │ │ ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Popⁿ │ POP │ A │ Pop address from stack and move it ║
║ │ │ │ to A ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Stacksizeⁿ │ SSZ │ A │ store the number of elements ║
║ │ │ │ currently on the stack in A ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
Remarks: If the descendant_count option is enabled, each process has
its own stack. If disabled, all of a program's processes access a
common stack (see 4.).
The RET (Return) instruction needs an operand because GSB (Gosub)
pushes a PC-relative address onto the stack. Usually, this operand
refers back to a label at the entry point of the subroutine ("RET
-10" for an entry point 10 addresses behind).
PSH (Push) and POP (Pop) instructions expand or shrink the program's
private stack. The stack can hold up to 127 instructions or data
statements. Popping an empty stack, as well as pushing past 127
elements is flagged with an execution error.
Special Instructions
╔══════════════════╤═════╤═════╤════════════════════════════════════╗
║ Instruction │ Mnem│ Args│ Description ║
╠══════════════════╪═════╪═════╪════════════════════════════════════╣
║ Protectⁿ │ PCT │ A │ Write-protect address A against ║
║ │ │ │ next write attempt ║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ Executeⁿ │ EXC │ A B │ Execute instruction at B, update B ║
║ │ │ │ & transfer control to A if no error║
╟──────────────────┼─────┼─────┼────────────────────────────────────╢
║ End │ END │ A │ Loader directive: end-of-program, ║
║ │ │(Opt)│ optionally begin execution at A ║
╚══════════════════╧═════╧═════╧════════════════════════════════════╝
Remarks: The END pseudo-opcode is optional and marks the end of the
program. If a program file does not contain an END statement, EOF is
assumed. The optional operand of END points to the first instruction
to be executed (e.g. END -15, if the program execution starts 15
instructions before). The default start is the first executable
instruction.
The EXC instruction is a single-thread meta-interpreter. It provides
Redcode programs with internal exception handling, since EXC traps
errors by conditional branching: if the instruction pointed to by B
fails or is a HLT instruction, then the next instruction following
EXC is executed. If the instruction at B succeeds, then B is updated
with the new "local" program counter (the address B transfers control
to), and execution resumes at A. B is therefore usually an indirect
address. Since only one local program counter is maintained in B,
only one execution thread can be trapped by EXC. Consequently, when
a SPL, SSP, or RLS instruction is executed by EXC, it will only
affect "global" threads. The code fragment below demonstrates a
single-instruction meta-interpreter executing a 3-instruction
program.
exc 0 @pc ;single instruction loop
jmp continue ;an error was trapped
pc: dat 1 ;local PC
loop: mov #0 @target ;"DWARF-like"
sub #10 2
jmp loop
target: dat 4
Since code executed by EXC is under control of the executing program,
it is "invisible" to the interpreter: e.g. single-step mode will not
trace the instructions under control of EXC, nor will breakpoints
trigger an interrupt. You can still debug code under the control of
EXC by placing a watchpoint on the data statement that serves as the
local program counter.
EXCs can be nested, i.e. an EXC instruction can execute another EXC
instruction. The interpreter can catch EXC "loops", i.e. it will
signal failure if an EXC tries to execute itself in an infinite loop.
┌─────────────────────────╖
│ 6.2. Addressing modes ║
╘═════════════════════════╝
Non-ICWS'88 modes are indicated with a ⁿ.
╔═════════════════════╤═══╤═════════════════════════════════════════╗
║ Mode │Sym│ Description ║
╠═════════════════════╪═══╪═════════════════════════════════════════╣
║ immediate │ # │ is data value ║
║ │ │ ║
║ direct │ $ │ is effective address ($ can be omitted) ║
║ │ │ ║
║ data-relative: │ │ ║
║ indirect │ @ │ is address of effective address ║
║ │ │ relative to data statement ║
║ pre-incrementⁿ│ > │ increment, is then address of effective ║
║ │ │ address relative to data statement ║
║ pre-decrement │ < │ decrement, is then address of effective ║
║ │ │ address relative to data statement ║
║ PC-relative: │ │ ║
║ indirectⁿ │ ^ │ is address of effective address ║
║ │ │ relative to program counter ║
║ pre-incrementⁿ│ / │ increment, is then address of effective ║
║ │ │ address relative to program counter ║
║ pre-decrementⁿ│ \ │ decrement, is then address of effective ║
║ │ │ address relative to program counter ║
╚═════════════════════╧═══╧═════════════════════════════════════════╝
Two modes of indirect addressing are implemented: (a) data-relative,
where the effective address is calculated by adding the value of the
referenced data statement (or B-field value of an executable
instruction) to its address, and (b) PC-relative, where the value of
the referenced data statement is added to the address of the
instruction that is currently executing. Data-relative indirect
addressing is part of the original Redcode specifications introduced
by A.K.Dewdney and the ICWS'88, whereas PC-relative addressing was
mistakenly implemented as the only form of indirect addressing in
pre-V2.0 versions of CoreWar Pro. Both modes are supported in order
to maintain compatibility with both programs written for earlier
versions of CoreWar Pro, and programs that use standard data-relative
indirect addressing.
┌────────────────────────────╖
│ 6.3. Preprocessor syntax ║
╘════════════════════════════╝
V3.0=> CoreWar Pro includes a powerful, built-in Redcode preprocessor that
facilitates writing of programs. Preprocessor features include
label-based references, constant definitions (EQUates), evaluation of
integer expressions and access to system variables.
┌─────────────────────────╖
│ 6.3.1. General format ║
╘═════════════════════════╝
Redcode program files are relatively free-format, but you should
establish and adhere to your own format conventions for clarity. The
preprocessor is case-insensitive; empty lines are permitted.
Opcodes, labels, numbers, etc. can be separated by space(s), tab(s)
or comma(ta). Separators are not required before and after
non-alphanumeric characters. E.g.: "Choice: DJN @Start <Counter"
could be written as "Choice:DJN@Start<Counter". An exception to this
rule is the '-' (minus) character which is interpreted as the start
of a negative number in "ADD 3 -2", but as the subtraction-operator
in "ADD 3 - 2 2" or "ADD 3-2 2".
┌─────────────────╖
│ 6.3.2. Labels ║
╘═════════════════╝
Labels are used to refer to addresses directly, rather than relative
V3.0=> to the program counter as in Plain Redcode. Labels are names that
consist of letters, numerals and the underscore and that start with a
letter or underscore.
Every label must end with a colon, but the colon is ommitted when the
label is referenced by an instruction. Labels can be on a separate
line before or on the same line with an instruction. You can have
more than one label per instruction. E.g.:
LastInstr:Endless: jmp endless
is the same as
Endless:
jmp ENDLESS LastInstr:
┌────────────────╖
│ 6.3. EQUates ║
╘════════════════╝
The EQU (Equate) statement defines a name for a list of symbols used
in the following code. RPP will replace every occurence of the first
argument of EQU in the code with what follows after the first
argument. EQU is similar to the #define preprocessor directive in C.
EQUates may be nested, that is the list of symbols to be substituted
may contain other EQUated names. EQUates have the format
Name EQU Symbol [..]
or
EQU Name Symbol [..]
E.g.:
numberlines equ (last-first+1)
equ bombzero mov #0
The first format is part of the ICWS'88 Redcode definition; the
second format is supported for compatibility with CoreWar Pro V2.0
and earlier. It is good practice to surround EQUated expressions with
parentheses to enforce evaluation precedence.
┌───────────────────────────╖
│ 6.3.4. System variables ║
╘═══════════════════════════╝
By refering to system variables you can write Redcode programs that
adapt to the current system configuration. There are four system
variables:
CORESIZE. The CORESIZE variable is instantiated to the current size
of the Core as determined by the coresize/1 predicate in the
configuration file (see 4.). The following fragment defines
the Coresize-dependent constant process_spacing:
equ n_processes 4
equ process_spacing (CORESIZE / n_processes)
V3.0=> RANDOM_ADDRESS. At load-time, the system variable RANDOM_ADDRESS is
instantiated to a random number between 0 and Coresize-1, which is
the same for each reference to RANDOM_ADDRESS within a program, but
different between programs. RANDOM_ADDRESS can be used to create
unique "program IDs" or to add some unpredictable behavior. In the
example below, n_processes can range from 2 to 5.
equ n_processes (RANDOM_ADDRESS % 4 + 2)
V3.0=> ADDRESS_SPACE. The value of ADDRESS_SPACE corresponds to the value of
the address_space/1 configuration predicate (see 4.,
7.2.).
V3.0=> PROCESS_LIMIT. This variable is set to the value of the
process_limit/1 configuration predicate (see 4., 7.1.).
System variables are implemented as predefined EQUate statements and
can therefore be overridden by EQUates in the program code.
┌──────────────────────╖
│ 6.3.5. Expressions ║
╘══════════════════════╝
Numerical expressions can be embedded anywhere in the program text.
The preprocessor evaluates an expression and substitutes it with the
integer result. Expressions consist of operators and operands.
Operators are:
+ addition
- subtraction
* multiplication
/ integer division
% modulo
Operands can be integers, labels, expressions or symbols representing
integers, labels or expressions. Two notations are supported:
standard infix (A + B) and reverse-polish (A B +). You can mix infix
and reverse-polish notation in the same expression, although this
would not exactly add to the readability of your code.
V3.0=> In infix notation, the order of evaluation is left to right; operator
precedence (*,/,% before +,-) is not supported, but parentheses can
be used to control evaluation order.
Reverse-polish expressions must be enclosed in parentheses to avoid
ambiguities such as the following:
1) ADD 2 2 - 3 => ADD (2 2 -) 3 => ADD 0 3 (reverse-polish)
2) ADD 2 2 - 3 => ADD 2 (2 - 3) => ADD 2 -1 (infix)
Examples:
MOV #last-first+1 numlines ; infix
ADD @2 * (CORESIZE + 2) counter ; infix with parentheses
spacing EQU (CORESIZE 4 /) ; reverse-polish
jmp (spacing first + - choicepoint) ; reverse-polish, then infix
┌───────────────────╖
│ 6.3.6. Comments ║
╘═══════════════════╝
Two comment symbols are implemented: the ; (semi-colon), which is
ICWS'88 compatible, and the REM word. REM is supported for backward
compatibility with earlier CoreWar Pro versions and may not be
supported in future versions. The comment extends from the comment
symbol to the end of the line.
┌──────────────────────────────╖
│ 6.3.6. Order of processing ║
╘══════════════════════════════╝
The preprocessor first substitutes all EQUated names, goes on to
replace label-references by numbers, and lastly evaluates
expressions. This means that it is possible to EQUate labels.
┌─────────────────────────╖
│ 7. ICWS'88 extensions ║
╘═════════════════════════╝
Under the current Core War standard "DWARF-like" warriors that remain
stationary and bomb the Core systematically are favored over more
"intelligent" programs that copy themselves, spawn sub-processes and
are capable of self-repair. This is evidenced by the fact that the
last freely self-replicating warrior to win the annual tournament was
MICE in 1987. Most effective warriors currently try to disable their
opponent by "process explosion", for example by planting the
devastating "SPL 0" instruction into the opponent's code. While this
is perfectly legal, it might be considered unfair, since the entire
program grinds to a halt, and not just the process whose code
segment that was hit.
To promote more interesting warriors, Jon Newman has suggested
extensions to the current Core War standard ("Three Proposals for
future Core War standards" published in the Winter 1991 issue of The
Core War Newsletter). CoreWar Pro implements these changes while
maintaining compatibility with ICWS'88.
┌──────────────────────╖
│ 7.1. Process limit ║
╘══════════════════════╝
V3.0=> ICWS'88 does not specify a limit to the number of processes a warrior
can spawn off. This is why "SPL 0" bombs are so effective; the
affected warrior will stall by spawning off processes until the
memory allocated to the interpreter is filled. CoreWar Pro allows
defining an upper limit to the process count through the
process_limit/1 predicate in the configuration file (see 4.).
If the process limit is reached, SPL will not create a new process
but will merely transfer control to the following instruction. A low
process limit will effectively defang warriors that use "process
explosion".
┌──────────────────────╖
│ 7.2. Address space ║
╘══════════════════════╝
V3.0=> The address space extension is used to restrict the addressable range
of Core memory. With e.g. address_space(2000) in the configuration
file, CoreWar Pro normalizes operand values to a range of -1000 to
999. All direct Core references are restricted to this range;
indirect addressing accesses -2000 to 1999. This extension encourages
mobile programs: in order to seek out opponents in non-addressable
areas of Core, warriors have to copy themselves or spawn off
processes.
┌─────────────────────────╖
│ 7.3. Descendant count ║
╘═════════════════════════╝
V3.0=> The descendant count modification limits the number of processes that
a newly created process can spawn off. With descendant_count enabled
(see 4.), the B-operand of the SPLit instruction specifies the
maximum number of processes that the new process can create. This
limit includes children processes, children's children processes and
so on. E.g. "SPL X #0" creates a processes that cannot create
sub-processes and is therefore immune to "SPL 0" bombs (a SPLit
instruction would simply transfer control to the next instruction).
The "root" process has a descendant_count of ProcessLimit-1 (the
global processes-per-program limit set by the process_limit/1
configuration predicate). A process can change its own descendant
count by SPLitting off a sub-process with the desired descendant
count and committing suicide. You could thus write a largely "SPL 0"
resistant program by starting the code with
spl start #some_low_number
hlt
start: <Rest of code>
Additional resistance to process-explosion is conferred by the EXC
and SSP instructions: Since EXC can only follow a single
execution-thread, SPL executed by EXC will not create a new process.
Frequent execution of SSP could be used defensively to inactivate
subverted processes.
┌──────────────────────╖
│ 8. The Core Editor ║
╘══════════════════════╝
The Core Editor is a debugging tool for inspecting and modifying the
contents of the Core array. Invoked from the Monitor menu, the Core
Editor opens a window centered on the Core address that was executed
last. Each address is displayed as one line with the format:
Address Attr Instruction
3017 1W CMP #513 @-12
"Address" is in the range from 0 to CoreSize-1. The attribute
V3.0=> consists of a number which may be followed by a "W", "B", or "P".
The number is the "owner" attribute of this address and corresponds
to the number of the program that wrote to it last. The "W" indicates
that this address is marked as a watchpoint to be displayed when the
watchpoint switch is enabled on the control panel (see 9.).
Similarly, the "B" marks an address as a breakpoint. An address is
protected against the next write access if the "W" symbol is
displayed. The contents of the instruction field is displayed as
"Plain Redcode", i.e. with labels, expressions and symbols resolved
to numbers. "Empty" addresses are shown with blank attribute and
instruction fields.
A selection bar highlights the current address. You can move around
the Core using cursor-control keys and issue single-character
commands displayed on the status line:
Up-, Down-Arrow move selection bar up or down by
one address
Left-, Right-Arrow scroll screen up or down by one
address
<PgDn>, <PgUp> display next or previous screen (22
addresses)
<^PgDn>, <^PgUp> (Control-PgUp, -PgDn) jump 1/8th of
the Core size ahead or back
<Home> go to the top of the page
<End> go to the bottom of the page
<Del> Erase contents of current address
<G>oto go to specified address
(default is the current address
offset by the B-field of the current
address, i.e. a JMP @0 #Goto)
<E>dit edit current address
<F>ind find contents of address
<P>rot write-protect/deprotect current
address (equivalent to executing PCT
on this address/writing to it)
<B>reak toggle breakpoint flag
<W>atch toggle watchpoint flag
e<X>ec execute current address and move
selection bar to next PC
<Esc> return to Monitor menu
The <E>dit command allows you to change the instruction field of the
V3.0=> current address. The full preprocessor syntax is supported at the
prompt for a new instruction. This means that labels, expressions and
system variables can occur in the instruction. You can even key in an
EQUate statement, in which case the old instruction is not
overwritten. Labels and EQUated symbols remain valid for the current
editing session and are cleared upon exiting the Core Editor.
<F>ind prompts for an instruction to search for. Again, this
V3.0=> instruction may contain labels, expressions, etc.. If you hit <Enter>
at the prompt, the Editor will search for the next occurrence of the
instruction field of the currently selected address. The address
attribute is ignored in the search. The search instruction may be
specified incompletely using the * wildcard. The * can take the place
of the opcode, the A- and the B-field. E.g. "MOV * *" positions the
selection bar at the next MOV instruction, irrespective of operands.
"* 0 1" searches for any opcode with operands 0 1, "* * *" jumps to
the next non-empty address, and "* *" locates the next instruction
with an empty B-field.
The e<X>ecute command will try to execute the instruction currently
under the selection bar. If the address is executable, the screen is
refreshed to show updated Core addresses, and the selection bar moves
to the address that the executed instruction transfers control to. If
an executed instruction returns more than one new process counter -
as it is the case with SPL and RLS - only the first PC is traced.
This command is extremely useful for debugging code segments. In
conjunction with the <E>dit command, you can write write entire
programs into the Core and watch them execute.
┌───────────────────────────╖
│ 9. Run control switches ║
╘═══════════════════════════╝
The run control panel in the Monitor module has nine on/off switches
that control appearance and interrupt behavior of a Core War battle.
Three parameters control how the battle is represented on screen
(single step, visual, watch), the remaining six control under what
circumstances execution is paused.
Key interrupt ON: execution can be paused at any time by
pressing any key, OFF: execution can only be
interrupted by pressing Control-Break (usually
ON, except when "single step" is enabled).
Default: ON
Single step ON: trace mode for debugging, the instruction
executed is displayed in the main window in Core
Editor format (see $editp$.). Single step ON disables
all other switches (except Watch), since in this mode
execution is interrupted after each instruction
anyway.
Default: OFF
Visual ON: visual representation of Core War execution is
enabled. In visual mode, the Core is mapped to the
main window, with each address corresponding to one
position on the 22 * 78 character area (increasing
address from left to right, top to bottom). If the
Core size exceeds 22 * 78 = 1716 then adjacent Core
addresses may map to the same cursor position,
"condensing" the entire Core onto one screen.
Execution of a process is shown by writing its
identifying character and color to the main window at
coordinates corresponding to the current program
counter. Writing to Core addresses is indicated by a
different character and color (all program display
parameters can be customized by prodisplay/9 in
the configuration file, see 4).
Default: ON
Watch ON: the contents of addresses marked as watchpoints
(using <W> in the Core Editor) are displayed while
programs are running. The contents of the instruction
it points to as an indirect address is also displayed
on the same line. Besides watchpoints, the current
list of program counters and the contents of the
private stack are shown. OFF: no watch-information is
displayed. "Watch" is compatible with all other
execution views, although it is most commonly used
together with "Single step".
Default: OFF
Breakpoints ON: the scheduler pauses after an instruction at a
breakpoint address was executed (Address Mode =
4,5,6,7); OFF: although a breakpoint may have been
reached, execution is not interrupted. Breakpoints
can be marked from within the Core Editor.
Default: ON
Break on error ON: interrupt is invoked if an instruction cannot be
executed (e.g. a data statement), usually indicating
that the faulting process has been corrupted by a
contestant destructively modifying its code in Core.
OFF: execution continues through errors. The Monitor
terminates a faulting process. If a program has only
one process running (and no processes were suspended
by SSP), an execution error will terminate the
program.
Default: ON
V3.0=> Break on execute opponent
Each Core address has an "owner attribute", a 4-bit
field indicating which program has last modified it.
The contents of this flag is shown in the second
column of the Core Editor display (see 8.).
ON: the Monitor uses this information to generate an
interrupt if a program executes an instruction that
was last written to by a different program. This
interrupt thus signals imminent program failure.
Default: ON
V3.0=> Break on overwrite opponent
ON: An interrupt is generated if a program writes to
an address that has previously been modified by a
different program. This tends to signal program
failure earlier than "Break on execute opponent", but
also pauses at less critical events, such as one
program's bombs overwriting another program's bombs.
Default: OFF
Count-down from <Count>
ON: the count-down counter is decremented with each
excution of an instruction. If zero is reached,
execution is interrupted, but may be restarted since
the counter is automatically reset. The current count
is also displayed on the status line during a battle.
Default: OFF
┌───────────╖
│ 10. Bugs ║
╘═══════════╝
The program is very sensitive to format errors in the configuration
file, e.g. the SideKick Notepad appends a ^Z character to each file
edited, which causes CoreWar Pro to report an error upon start-up.
Most other ASCII-editors should work fine.
V3.0=> While there is no fixed limit on the number of Redcode programs that
can be run concurrently, program numbers greater than 31 will carry
from the "owner" field into first the breakpoint- and then the
protect status bit of address attributes. Consequently, programs with
program numbers greater than 31 will trigger false breakpoint
interrupts (unless turned off from the control panel). Programs above
63 will have all their instructions write-protected which is usually
undesirable.
┌──────────────────────╖
│ 11. Version history ║
╘══════════════════════╝
V1.0 to 1.5 (July-September 1988, not released)
V1.6 (released April 1989)
■ representation of Core as dynamic database predicates
■ color support
V1.7 (released November 1990)
■ Redcode preprocessor
■ condensed visual display of execution
■ stack opcodes
V2.0 (released March 1991, posted on c.b.i.p April 1)
■ more opcodes
■ Core editor
■ watchpoints
■ internal representation of instructions hidden
V2.1 (released August 1991)
■ ICWS'88 compliant
■ larger Core sizes
■ lower memory requirement
V3.0 (released November 1991)
■ faster execution
■ integration of preprocessor
■ EGA/VGA extended textmodes
■ ICWS'88 extensions
End of COREMAN.DOC, date of last change: 11-17-91